package com.hp.bon.sgw.wh.channel.handler;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.hp.bon.sgw.Constants;
import com.hp.bon.sgw.bean.XmlMessage;
import com.hp.bon.sgw.core.BuzProcessorManager;
import com.hp.bon.sgw.core.CallParam;
import com.hp.bon.sgw.core.channel.SoapChannel;
import com.hp.bon.sgw.core.channel.handler.IAsynCallHandler;
import com.hp.bon.sgw.threads.TaskManager;
import com.hp.bon.sgw.wh.bean.QryBalanceRecordDetailResponse;
import com.hp.bon.sgw.wh.service.UserResourceConfigService;
import com.hp.bon.sgw.wh.utils.LogUtil;
import com.hp.bon.sgw.wh.utils.ResultCodeUtil;
import com.hp.ocs.diameter.DiameterUtils;
import com.hp.ocs.diameter.message.*;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.simpleframework.http.Request;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName: QryBalanceRecordDetailHandle
 * @Description: 3.2.13余额变动明细查询 (下游DCC+新增webservice接口)
 */
public class QryBalanceRecordDetailHandle implements IAsynCallHandler {
	private static final Logger _log = LoggerFactory.getLogger(QryBalanceRecordDetailHandle.class);

	private static final Object XmlMessage = null;

	private PrintStream printStream;
	private JSONObject requestObject;
    private long startTime;
    private Request request;
	private UserResourceConfigService userResourceConfigService ;
	public QryBalanceRecordDetailHandle(PrintStream printStream, JSONObject requestObject, Request request, long startTime) {
		this.printStream = printStream;
		this.requestObject = requestObject;
        this.startTime = startTime;
        this.request = request;
	}

	@Override
	public int getProtocolType() {
		return 0;
	}

	@Override
	public void onCallResult(CallParam callParam) {
		XmlMessage ack = null;
		Object response = null;
		if (callParam.getResponse() != null) {
			_log.warn("getResponse():");
			response = callParam.getResponse();
		} else if (callParam.getRecvResponse() != null) {
			_log.warn("getRecvResponse():");
			response = callParam.getRecvResponse();
		}
		if (response == null) {
			int _retcodeTmp = callParam.getRetCode() == 3002 ? 11202 : callParam.getRetCode();
			ack = SoapChannel.createERRAnwser(callParam.getSessionId(), _retcodeTmp, callParam.getResultMsg());
			callParam.setServiceResultCode(_retcodeTmp);// 11203
		} else {
			if (response instanceof Message) {// CCA -> XML
                _log.info("================response instanceof Message");
                ack = BuzProcessorManager.getInstance().convertMessageToAck(callParam);
			} else if (response instanceof XmlMessage) {
                _log.info("================response instanceof XmlMessage");
                ack = (XmlMessage) response;
			} else {
				_log.warn("unknown response type:" + callParam.getResponse().getClass().getName());
			}
		}
		try {
			String respXML = convertResponseString(response, callParam.getServiceResultCode());
			if("0".equals(respXML)) {
				return;
			}
			byte[] resp = respXML.getBytes("UTF-8");
			ack.setLength(resp.length);
			ack.setMsgTime(System.currentTimeMillis());
			printStream.write(resp);
			printStream.close();
			callParam.setResponse(ack);
//			if (callParam.getRetCode() == Constants.ResultCode.SUCCESS) {// 成功的消息，请求应答入库
//				MessageDetail detail = new MessageDetail();
//				detail.setBusinessCallId(callParam.getBussinessCallId());
//				detail.setSessionId(callParam.getSessionId());
//				detail.setServiceContextId(callParam.getServiceContextId());
//				detail.setMessageType(MessageType.WSA);
//				detail.setDetails(ack.getDATA());
//				detail.setMsgTime(new Date(ack.getMsgTime()));
//				detail.setOpType("send");
//				detail.setHostId(callParam.getUserName());
//				MessageDetailCacheManager.getInstance().add(detail);
//			}
            //记录到日志
            LogUtil.saveLogToABM(request,respXML,startTime);
			TaskManager.taskProcess(callParam);
            _log.info("http response(cfq) " + respXML);

		} catch (UnsupportedEncodingException e) {
			_log.info("convertResponseString UnsupportedEncodingException error,msg=" + e.getMessage());
		} catch (IOException e) {
			_log.info("convertResponseString IOException,msg=" + e.getMessage());
		}catch (Exception e) {
			e.printStackTrace();
			_log.error("convertResponseString IOException,msg=" + e.getMessage());
		}
	}
	

	
	
	/**
	 * 返回最终json格式数据
	 * @param answer
	 * @param serviceResultCode
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private String convertResponseString(Object answer, int serviceResultCode) {
		_log.error("QryBalanceRecordDetailHandle serviceResultCode = {}", serviceResultCode);
        _log.info("===========service_result_code===============" + serviceResultCode);
        String response = "";
		Map<String, Object> data = new HashMap<String, Object>();
		String HomeAreaCode=null;
		String Result=null;//DCC返回码
		String areaCode=null;
		String latnId=null;
		if (answer instanceof Message) {
			_log.info("===================解析为Message  非定制流程=========================");
			//AVP解析
			Message message=(Message) answer;
			Map<String, Object> map= getAvpsFromMessage(message);//DCC返回结果
			if(map != null) {
				latnId=(String)map.get("latnId");
				areaCode =(String)map.get("areaCode");
				HomeAreaCode =(String)map.get("HomeAreaCode");
				Result =(String)map.get("Result");
			}
		}else if (answer instanceof XmlMessage) {
			_log.info("===================解析为XmlMessage  定制流程格式=========================");
			//XML解析
			XmlMessage xmlMessage=(XmlMessage) answer;
			String xmlMessageData = xmlMessage.getDATA();
			_log.info("xmlMessage.getDATA():"+xmlMessageData);
			if(xmlMessageData.indexOf("<HomeAreaCode>") >= 0) {
				HomeAreaCode=xmlMessageData.substring(xmlMessageData.indexOf("<HomeAreaCode>")+14,xmlMessageData.indexOf("</HomeAreaCode>"));
			}
			if(xmlMessageData.indexOf("<Result>") >= 0) {
				Result=xmlMessageData.substring(xmlMessageData.indexOf("<Result>")+8,xmlMessageData.indexOf("</Result>"));
			}
		}
		_log.info("===================HomeAreaCode:"+HomeAreaCode+"===================Result:"+Result);
		_log.info("===================latnId:"+latnId+"===================Result:"+Result);
		serviceResultCode=Integer.valueOf(Result);
        _log.info("===========service_result_code===============" + Result);

		Gson gson = new Gson();
		if (null == HomeAreaCode && latnId == null && areaCode == null) {
			data.put("resultCode", "-1");
			data.put("resultMsg", "查询失败");
		}else if(serviceResultCode != 0){
			// 如果返回了错误码，则将错误信息转给用户
            data.put("resultCode", serviceResultCode+"");
            data.put("resultMsg", "查询失败");
		}else{
			// 调用webservice接口查询详单信息
			String jf3_flag=userResourceConfigService.getValue("jf3_flag", "0");
			if("1".equals(jf3_flag) && "1".equals(getVersionType(latnId, "0"))) {
				_log.info("================调用新接口===========================");
				//调用新接口 走DCC
				String objType = requestObject.getJSONObject("svcObjectStruct").getString("objType");
				String objValue = requestObject.getJSONObject("svcObjectStruct").getString("objValue");
				String objAttr = requestObject.getJSONObject("svcObjectStruct").getString("objAttr");
				String dataArea = requestObject.getJSONObject("svcObjectStruct").getString("dataArea");
				Element serviceInformation = DocumentHelper.createElement("Service_Information");
				serviceInformation.addElement("Channel_Id").setText("200");
				serviceInformation.addElement("Area_Code").setText(areaCode);
				serviceInformation.addElement("DestinationAttr").setText(objAttr);
				serviceInformation.addElement("Destination_Id").setText(objValue);
				serviceInformation.addElement("Destination_Id_Type").setText("2");
				serviceInformation.addElement("Billing_Cycle").setText(requestObject.getString("billingCycleId"));
				XmlMessage req = new XmlMessage(true);
				String tmallHostId = "SGWHBCFQ@027.ctnbc-bon.net";
				String sessionId = DiameterUtils.makeSessionID(tmallHostId);
				req.setIp(requestObject.getString("IP"));
				req.setMsgTime(System.currentTimeMillis());
				req.setMID(sessionId);
				req.setUID(tmallHostId);
				req.setSCID("BalanceRecordDetail.jf3@027.ctnbc-bon.net");
				req.setSIG(null);
				req.setREPTAG(0);
				req.setDATA(serviceInformation.asXML());
				req.setDataElement(serviceInformation);
				// new CallParam对象
				QryBalanceRecordDetailHandle2 returnBalanceHandle = new QryBalanceRecordDetailHandle2(printStream,requestObject,request,startTime);
				CallParam callParam = new CallParam(req.getMID(), req.getSCID(), req, req.getUID(), returnBalanceHandle);
				BuzProcessorManager.getInstance().processRequest(callParam);
				return "0";
				
			}
			_log.info("================调用旧接口===========================");
			if(HomeAreaCode == null){
                HomeAreaCode = latnId;
            }
			String url="1001".equals(HomeAreaCode) ? requestObject.getString("YECXURLWH") : requestObject.getString("YECXURLHB");
			//Map<String, Object> Data_Information = (Map<String, Object>) map.get("Service_Information");
			String buildStringMes = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:cli=\"http://boss3.service.boss/client/\">"
			  +" <soapenv:Header/>"
			  +" <soapenv:Body>"
			  +"    <cli:QryBalanceRecordDetailRequest>"
			  +"       <cli:billingCycleId>"+requestObject.getString("billingCycleId")+"</cli:billingCycleId>"
			  +"       <cli:operAttrStruct>"
			  +"         <cli:staffId>"+requestObject.getJSONObject("operAttrStruct").getString("staffId")+"</cli:staffId>"
			  +"          <cli:operOrgId>"+requestObject.getJSONObject("operAttrStruct").getString("operOrgId")+"</cli:operOrgId>"
			  +"          <cli:operTime>"+requestObject.getJSONObject("operAttrStruct").getString("operTime")+"</cli:operTime>"
			  +"          <cli:operPost>"+requestObject.getJSONObject("operAttrStruct").getString("operPost")+"</cli:operPost>"
			  +"          <cli:operServiceId>"+requestObject.getJSONObject("operAttrStruct").getString("operServiceId")+"</cli:operServiceId>"
			  +"          <cli:lanId>"+requestObject.getJSONObject("operAttrStruct").getString("lanId")+"</cli:lanId>"
			  +"       </cli:operAttrStruct>"
			  +"       <cli:svcObjectStruct>"
			  +"           <cli:objType>"+requestObject.getJSONObject("svcObjectStruct").getString("objType")+"</cli:objType>"
			  +"           <cli:objValue>"+requestObject.getJSONObject("svcObjectStruct").getString("objValue")+"</cli:objValue>"
			  +"           <cli:objAttr>"+requestObject.getJSONObject("svcObjectStruct").getString("objAttr")+"</cli:objAttr>"
			  +"           <cli:dataArea>"+requestObject.getJSONObject("svcObjectStruct").getString("dataArea")+"</cli:dataArea>"
			  +"        </cli:svcObjectStruct>"
			  +"     </cli:QryBalanceRecordDetailRequest>"
			  +"  </soapenv:Body>"
			  +"</soapenv:Envelope>";

            QryBalanceRecordDetailResponse qryBalanceRecordDetailResponse = null;
			try{
				String resp = sendWebService(buildStringMes,url);
				XStream xstream2 = new XStream(new DomDriver());
				xstream2.alias("QryBalanceRecordDetailResponse", QryBalanceRecordDetailResponse.class);
				xstream2.alias("balanceChangeList", QryBalanceRecordDetailResponse.BalanceChangeList.class);//节点名称对应类
				xstream2.addImplicitCollection(QryBalanceRecordDetailResponse.class, "balanceChangeList");//list节点名称
				qryBalanceRecordDetailResponse = (QryBalanceRecordDetailResponse) xstream2.fromXML(resp.substring(resp.indexOf("<QryBalanceRecordDetailResponse"), resp.indexOf("</soapenv:Body>")));
			}catch(Exception e){
				_log.error("详单webservice调用异常：", e);
			}
			if(qryBalanceRecordDetailResponse == null) {
				// 调用webservice接口失败
				data.put("resultCode", "-1");
				data.put("resultMsg", "查询失败");
			}else {
				if(qryBalanceRecordDetailResponse.getResultCode() != null) {
                    String newCode = ResultCodeUtil.updateResultCode(qryBalanceRecordDetailResponse.getResultCode(), userResourceConfigService.getValue("api_resultCode"), userResourceConfigService.getValue("api_defaultResult"));
					qryBalanceRecordDetailResponse.setResultCode(newCode);
				}
				return getResult(gson.toJson(qryBalanceRecordDetailResponse));
			}
		}
        String newCode = ResultCodeUtil.updateResultCode(data.get("resultCode"), userResourceConfigService.getValue("api_resultCode"), userResourceConfigService.getValue("api_defaultResult"));
        data.put("resultCode", newCode);
        return gson.toJson(data);
	}

    /**
     * 处理paymentChannel 字段为空 ,并且转换为 Long类型
     * @return
     */
    private static String getResult(String gsonString){
        JSONObject jsonObject=JSONObject.parseObject(gsonString);
        JSONArray jsonArray=jsonObject.getJSONArray("balanceChangeList");
        if (jsonArray != null && !jsonArray.isEmpty()){
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject temp=jsonArray.getJSONObject(i);
                temp.put("billingCycleId",temp.getLongValue("billingCycleId"));
                temp.put("balanceVal",temp.getLongValue("balanceVal"));
                temp.put("beforeBalanceVal",temp.getLongValue("beforeBalanceVal"));
                temp.put("afterBalanceVal",temp.getLongValue("afterBalanceVal"));
                temp.put("balanceIn",temp.getLongValue("balanceIn"));
                temp.put("balanceOut",temp.getLongValue("balanceOut"));
                temp.put("balanceEnd",temp.getLongValue("balanceEnd"));
                temp.put("balanceTypeFlag",temp.getLongValue("balanceTypeFlag"));
            }
        }
        return jsonObject.toJSONString();
    }
	
	/**
	 * 处理CCA结果
	 * @param answer
	 * @return
	 */
	public Map<String, Object> getAvpsFromMessage(Message answer) {
		Map<String, Object> map = new HashMap<String, Object>();
		try {
			AVP avp = answer.find(Constants.DIAMETER_AVP_SERVICE_INFOMATION, Constants.DIAMETER_VENDOR_3GPP);
			AVP_Grouped avpServiceInfomation = new AVP_Grouped(avp);
			AVP[] avps = avpServiceInfomation.queryAVPs();
			for (AVP avpData : avps) {
				
				if (avpData.code() == 20631 && avpData.vendorID() == Constants.DIAMETER_VENDOR_CT) {
					map.put("Result", String.valueOf(new AVP_Unsigned32(avpData).queryValue()));
				}
				if (avpData.code() == 80615 && avpData.vendorID() == Constants.DIAMETER_VENDOR_CT) {
					map.put("HomeAreaCode", String.valueOf(new AVP_Unsigned32(avpData).queryValue()));
				}
				if (avpData.code() == 50207 && avpData.vendorID() == Constants.DIAMETER_VENDOR_CT) {
					map.put("areaCode",new AVP_UTF8String(avpData).queryValue());
				}
				if (avpData.code() == 80411 && avpData.vendorID() == Constants.DIAMETER_VENDOR_CT) {
					map.put("latnId", new AVP_UTF8String(avpData).queryValue());
				}
				
			}
		} catch (Exception e) {
			map = null;
			_log.info("getAvpsFromMessage Exception error,msg=" + e.getMessage());
		}
		return map;
	}

	
	/**
	 * 调用详单查询webservice接口
	 * @param param
	 * @return
	 */
	private String sendWebService(String param,String url) {
		_log.info("===========WebServiceProcessor url===============" + url);
		_log.info("===========WebServiceProcessor param===============" + param);
		String resp = "";
		PostMethod post = new PostMethod(url);
		try {
			RequestEntity requestEntity = new StringRequestEntity(param, "text/xml", "UTF-8");
			post.setRequestEntity(requestEntity);
			post.setRequestHeader("SOAPAction", "text/xml; charset=utf-8");
			HttpClient client = new HttpClient();
			client.getHttpConnectionManager().getParams().setConnectionTimeout(5 * 1000);
			client.getHttpConnectionManager().getParams().setSoTimeout(5000);
			client.executeMethod(post);
			resp = post.getResponseBodyAsString();
		} catch (UnsupportedEncodingException e) {
			_log.error("===========" + url + " call UnsupportedEncodingException===============", e);
		} catch (HttpException e) {
			_log.error("===========" + url + " call HttpException===============", e);
		} catch (IOException e) {
			_log.error("===========" + url + " call IOException===============", e);
		}
		_log.info("===========WebServiceProcessor resp===============" + resp);
		return resp;
	}
	
	/**
	 * 由于计费侧提供的接口协议没变，只是地址调整，割接到3.0的本地网需要调用新的地址
	 * 集团电子发票API接口调整
	 * 获取判断使用的地址
	 * jf3_flag 刷新开关  配置为1则表示启用割接地市判断，配置为0则表示按现有的流程
	 * Jf3_jt_latn_id  割接地市配置项（多个地市用逗号分隔，如果配置项调整为888，则表示全部调用新地址）
	 * resultLanIdStr 区域编码
	 * cityId
	 * jf3_jt_latn_id 是84201这种
		jf3_latn_id是1001 1018 这种
		jf3_area_coee是027 0716 这种
		type 传参0 1001类 传1 84210类   返参 1 新 0 旧的
	 */
	private String getVersionType(String cityId,String type) {
		String jf3_flag = userResourceConfigService.getValue("jf3_flag","");////增加刷新开关  ,配置为1则表示启用割接地市判断，配置为0则表示按现有的流程
		String jf3_jt_latn_id = userResourceConfigService.getValue("jf3_jt_latn_id","");
		String jf3_latn_id = userResourceConfigService.getValue("jf3_latn_id","");
		_log.info("=============cityId==================="+cityId);
		_log.info("=============jf3_flag==================="+jf3_flag);
		_log.info("=============jf3_jt_latn_id============="+jf3_jt_latn_id);
		_log.info("=============jf3_latn_id================"+jf3_latn_id);
		String str;
		if("0".equals(type)) {
			//1001类型
			str = jf3_latn_id;
		}else {
			//84201 类型
			str = jf3_jt_latn_id;
		}
		//1 新流程  0 旧的流程
		if("1".equals(jf3_flag)) {
			if("888".equals(str)) {
				return "1";//新的
			}else {
				String[] split_jt_latn_id = str.split(",");
				for (String string : split_jt_latn_id) {
					if(string.equals(cityId)) {
						//包含,仅区分新旧
						return "1";//新的 Recharged.jf3@027.ctnbc-bon.net
					}
				}
			}
			
		}
		return "0";//旧的 SeverRecharge.SGWPAY@027.ctnbc-bon.net  
	}
	
	private String getAreaCode(String homeAreaCode) {
		String [][]  arr1= {{"1001","027"},{"1003","0710"},{"1004","0713"},{"1005","0717"},{"1006","0712"},
				{"1007","0711"},{"1008","0715"},{"1009","0719"},{"1010","0724"},{"1011","0714"},{"1012","0722"},
				{"1013","0718"},{"1014","0728"},{"1015","0728"},{"1016","0728"},{"1017","0719"},{"1018","0716"}};
		for (String[] strings : arr1) {
			if(homeAreaCode.equals(strings[0])) {
				return strings[1];
			}
		}
		return "027";
	}
	
}
